Concurrency এর জন্য Design Patterns (Producer-Consumer, Readers-Writers)

Java Technologies - জাভা কনকারেন্সি (Java Concurrency) - Advanced Concurrency Patterns এবং Best Practices
260

জাভাতে মাল্টিথ্রেডিং ও কনকারেন্সি ব্যবস্থাপনা সহজ করার জন্য কিছু ক্লাসিক্যাল Design Patterns ব্যবহার করা হয়। এর মধ্যে সবচেয়ে গুরুত্বপূর্ণ দুটি হল:

  1. Producer-Consumer Pattern
  2. Readers-Writers Pattern

১. Producer-Consumer Pattern

বিবরণ:

  • Producer-Consumer প্যাটার্ন একটি সাধারণ কনকারেন্সি সমস্যা যেখানে একাধিক প্রযোজক (Producer) ডেটা তৈরি করে এবং একাধিক গ্রাহক (Consumer) সেই ডেটা প্রসেস করে।
  • BlockingQueue ব্যবহার করলে এটি সহজ হয়।

সমস্যার সমাধান:

  • একটি shared buffer (queue) ব্যবহার করা হয়।
  • প্রযোজক ডেটা যোগ করে এবং গ্রাহক ডেটা তুলে নেয়।
  • যদি কিউ পূর্ণ থাকে, প্রযোজক অপেক্ষা করে।
  • যদি কিউ খালি থাকে, গ্রাহক অপেক্ষা করে।

উদাহরণ:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

class Producer implements Runnable {
    private BlockingQueue<Integer> queue;

    public Producer(BlockingQueue<Integer> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            for (int i = 1; i <= 10; i++) {
                System.out.println("Produced: " + i);
                queue.put(i); // কিউতে ডেটা যোগ করা
                Thread.sleep(500); // ডেটা তৈরি করার সময়
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

class Consumer implements Runnable {
    private BlockingQueue<Integer> queue;

    public Consumer(BlockingQueue<Integer> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            while (true) {
                Integer data = queue.take(); // কিউ থেকে ডেটা নেওয়া
                System.out.println("Consumed: " + data);
                Thread.sleep(1000); // ডেটা প্রসেস করার সময়
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

public class ProducerConsumerExample {
    public static void main(String[] args) {
        BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);

        Thread producerThread = new Thread(new Producer(queue));
        Thread consumerThread = new Thread(new Consumer(queue));

        producerThread.start();
        consumerThread.start();
    }
}

কী ঘটবে:

  1. প্রযোজক ডেটা তৈরি করে কিউতে যোগ করবে।
  2. গ্রাহক কিউ থেকে ডেটা তুলে নেবে।
  3. কিউ পূর্ণ হলে প্রযোজক থামবে এবং কিউ খালি হলে গ্রাহক থামবে।

২. Readers-Writers Pattern

বিবরণ:

  • Readers-Writers প্যাটার্ন এমন পরিস্থিতিতে ব্যবহৃত হয় যেখানে অনেক থ্রেড পড়তে (read) এবং কিছু থ্রেড লিখতে (write) চায়।
  • লক্ষ্য:
    1. রিডারদের মধ্যে সমান্তরাল পড়ার অনুমতি দিন।
    2. রাইটারদের একচেটিয়াভাবে (exclusive) লিখতে দিন।
    3. রিডার ও রাইটারদের মধ্যে প্রায়োরিটি সঠিকভাবে বজায় রাখুন।

উদাহরণ:

import java.util.concurrent.locks.ReentrantReadWriteLock;

class SharedResource {
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private int data = 0;

    public void write(int value) {
        lock.writeLock().lock(); // রাইট লক নিন
        try {
            System.out.println(Thread.currentThread().getName() + " is writing: " + value);
            data = value;
            Thread.sleep(1000); // লেখার সময়
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.writeLock().unlock(); // রাইট লক মুক্ত করুন
        }
    }

    public int read() {
        lock.readLock().lock(); // রিড লক নিন
        try {
            System.out.println(Thread.currentThread().getName() + " is reading: " + data);
            Thread.sleep(500); // পড়ার সময়
            return data;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return -1;
        } finally {
            lock.readLock().unlock(); // রিড লক মুক্ত করুন
        }
    }
}

public class ReadersWritersExample {
    public static void main(String[] args) {
        SharedResource resource = new SharedResource();

        // রিডার থ্রেড
        Runnable readerTask = () -> {
            while (true) {
                resource.read();
            }
        };

        // রাইটার থ্রেড
        Runnable writerTask = () -> {
            int value = 1;
            while (true) {
                resource.write(value++);
            }
        };

        // থ্রেড চালানো
        Thread reader1 = new Thread(readerTask, "Reader-1");
        Thread reader2 = new Thread(readerTask, "Reader-2");
        Thread writer = new Thread(writerTask, "Writer");

        reader1.start();
        reader2.start();
        writer.start();
    }
}

কী ঘটবে:

  1. রিডাররা একসঙ্গে পড়তে পারবে।
  2. রাইটার একা ডেটা লিখবে এবং সেই সময় অন্য রিডার বা রাইটার ঢুকতে পারবে না।

Producer-Consumer এবং Readers-Writers এর তুলনা

বৈশিষ্ট্যProducer-ConsumerReaders-Writers
ব্যবহার ক্ষেত্রডেটা উৎপাদন ও ব্যবস্থাপনাপড়া ও লেখা পরিচালনা
থ্রেড সমন্বয়প্রযোজক এবং গ্রাহকের মধ্যে সমন্বয়রিডার এবং রাইটারের মধ্যে সমন্বয়
কনকারেন্সি লেভেলপ্রযোজক বা গ্রাহক একত্রে কাজ করতে পারে নাএকাধিক রিডার একত্রে কাজ করতে পারে
সুবিধাসরল এবং থ্রেড-সেফডেটার উপর নিয়ন্ত্রণ এবং সমান্তরাল পড়া

  1. Producer-Consumer Pattern:
    • ব্যবহার করুন যখন একটি থ্রেড ডেটা তৈরি করবে এবং অন্যটি তা প্রসেস করবে।
    • BlockingQueue এর মত স্ট্রাকচার ব্যবহার করে সহজ করা যায়।
  2. Readers-Writers Pattern:
    • ব্যবহার করুন যেখানে পড়ার অপারেশন বেশি এবং লেখার অপারেশন কম।
    • ReentrantReadWriteLock এর মাধ্যমে রিডারদের সমান্তরাল পড়ার অনুমতি দিন এবং রাইটারদের একচেটিয়াভাবে লিখতে দিন।

এই প্যাটার্নগুলো সঠিকভাবে প্রয়োগ করলে মাল্টিথ্রেডেড অ্যাপ্লিকেশন আরও কার্যকর ও দক্ষ হবে।

Content added By
Promotion
NEW SATT AI এখন আপনাকে সাহায্য করতে পারে।

Are you sure to start over?

Loading...